package cn.dt.ymcc.service.impl;

import cn.dt.ymcc.domain.Login;
import cn.dt.ymcc.domain.User;
import cn.dt.ymcc.domain.UserAccount;
import cn.dt.ymcc.domain.UserBaseInfo;
import cn.dt.ymcc.dto.RegisterDto;
import cn.dt.ymcc.feign.UaaLoginFeignClient;
import cn.dt.ymcc.mapper.UserMapper;
import cn.dt.ymcc.result.JSONResult;
import cn.dt.ymcc.service.IUserAccountService;
import cn.dt.ymcc.service.IUserBaseInfoService;
import cn.dt.ymcc.service.IUserService;
import cn.dt.ymcc.util.AssertUtil;
import cn.dt.ymcc.util.BitStatesUtils;
import cn.dt.ymcc.util.StrUtils;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author whale.dai
 * @since 2022-07-15
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;
    @Autowired
    private UaaLoginFeignClient uaaLoginFeignClient;
    @Autowired
    private IUserService userService;
    @Autowired
    private IUserBaseInfoService userBaseInfoService;
    @Autowired
    private IUserAccountService userAccountService;

    @Override
    public User getUserByphone(String phone) {
        return userMapper.getUserByphone(phone);
    }

    /**
     * 1. 基本参数校验（使用jsr303校验了）
     * 2. 手机验证码校验
     *  从redis中获取手机验证码判断
     * 3. 手机是否已经被注册校验
     * 4. 远程保存login登录信息[Feign远程调用]
     * 5. 保存user注册信息
     * 6. 保存user_base_info基本信息
     * 7. 保存user_account账户
     * 8. 删除Redis中的手机验证码
     * @param dto
     */
    @Override
    @GlobalTransactional
    public void registerByPhone(RegisterDto dto) {
//        手机验证码校验
        String code = dto.getSmsCode();
        String phone = dto.getMobile();
        String phoneKey = "register:" + phone;
        //此处smsCodeTmp带有时间戳

        Object smsCodeTmp = redisTemplate.opsForValue().get(phoneKey);
//        判断是否过期，过期了就提醒
        AssertUtil.isNotNull(smsCodeTmp, "手机验证码已失效，请重新获取");
        //* 4.校验手机验证码是否和内存中的一致，不一致提醒
//        获取到内存中的手机验证码，
        String memoryCode = smsCodeTmp.toString().split(":")[0];
        AssertUtil.isEquals(memoryCode,code,"验证码不一致，请重新输入");
        String registerCode = dto.getRegisterCode();
//        通过注册邀请码查询到用户，将user的id绑到refer_id;
        User userByRegisterCode = userMapper.getUserByRegisterCode(dto.getRegisterCode());
        AssertUtil.isNotNull(userByRegisterCode,"邀请人不存在，请重新找个邀请人");
        //保存表
    //        远程保存login登录信息[Feign远程调用]
        JSONResult innitLogin = innitLogin(dto);
        //一定有返回值，不管成功与否
        AssertUtil.isTrue(innitLogin.isSuccess(),innitLogin.getMessage());
        Long loginId = Long.valueOf(innitLogin.getData().toString());
        AssertUtil.isNotNull(loginId,"保存login表失败了哦");
        //        保存user注册信息
        User user = innitUser(loginId, phone);
        AssertUtil.isNotNull(user.getId(),"保存user失败了");
        //        保存user_base_info基本信息
        innitBaseInfo(user.getId(),dto.getRegChannel(),userByRegisterCode.getId());
    //        保存user_account账户
        innitAccount(user.getId());

    }

    /**
     * 通过注册码查询用户
     * @param registerCode
     * @return
     */
    @Override
    public User getUserByRegisterCode(String registerCode) {
        return userMapper.getUserByRegisterCode(registerCode);
    }

    private void innitAccount(Long id) {
        UserAccount account = new UserAccount();
        account.setId(id);
        account.setCreateTime(new Date().getTime());
        userAccountService.insert(account);
    }

    /**
     *  保存user_base_info基本信息
     */
    private void innitBaseInfo(Long id,Integer regChannel,Long codeUserId) {
        UserBaseInfo info = new UserBaseInfo();
        info.setId(id);
        //@TODO
        info.setReferId(codeUserId);
        info.setCreateTime(new Date().getTime());
        info.setRegChannel(regChannel);//注册渠道
        userBaseInfoService.insert(info);
    }

    /**
     * 保存user表
     */
    private User innitUser(Long loginId,String phone) {
        User user = new User();
        user.setLoginId(loginId);
        user.setPhone(phone);
        user.setNickName(phone);
        user.setCreateTime(new Date().getTime());
//        保存user表
        /*
        位状态（使用二进制位表示状态最大64位）
        * 已激活 OP_ACTIVED
        * 手机认证 OP_AUTHED_PHONE
        * 注册成功的标示 OP_REGISTED
        * */
        long state = BitStatesUtils.addState(BitStatesUtils.OP_ACTIVED,BitStatesUtils.OP_REGISTED );
        state = BitStatesUtils.addState(state, BitStatesUtils.OP_AUTHED_PHONE);
        user.setBitState(state);
        user.setCode(StrUtils.getRandomString(4));
        userService.insert(user);
        return user;

    }


    /**
     * 保存login表
     * @param dto
     * @return
     */
    private JSONResult innitLogin(RegisterDto dto) {
        Login login = new Login();
        login.setUsername(dto.getMobile());
        login.setPassword(dto.getPassword());
        login.setType(1);
        login.setEnabled(true);
        return uaaLoginFeignClient.saveOrUpdate(login);



    }
}
